<?php

namespace App\Models\Common;

use App\Helpers\Code;
use App\Models\Account\User;
use App\Models\Account\UserGroupMenuActionScope;
use App\Models\BaseModel;
use Illuminate\Support\Facades\DB;

class DataScope extends BaseModel
{

    protected $table = 'data_scopes';
    protected $fillable = [
        'parent_id', 'title', 'full_title', 'code', 'data_scope', 'description',
    ];
    public $params = ['title'];
    public $sorters = ['title', 'data_scope'];

    public function users()
    {
        return $this->hasMany('App\Models\Account\User', 'scope_id');
    }

    /**
     * 添加数据域
     * @param $data
     * @return null
     */
    public function addScope($data)
    {
        if (!isset($data['parent_id'])) {
            $data['full_title'] = $data['title'];

            $data['data_scope'] = $this->_setScope(true);

            return $this->create($data);
        } else {
            $model = $this->find($data['parent_id']);

            if (!$model) {
                return null;
            }

            $data['full_title'] = $model->full_title . '\\' . $data['title'];
            $data['data_scope'] = $this->_setScope(false, $data['parent_id'], $model->data_scope);

            return $this->create($data);
        }
    }

    /**
     * 删除数据域
     * @param $id
     * @return int|null
     * todo:判断是否有其他地方在用  比如  用户
     */
    public function deleteScope($id)
    {
        $model = $this->find($id);
        if (!$model) {
            return null;
        }

        $child = $this->where('parent_id', $id)->count();
        if ($child > 0) {
            return Code::INSIDE_ERROR;
        }

        $user = User::where('scope_id', $id)->count();
        if ($user > 0) {
            return Code::INSIDE_ERROR_1;
        }

        $menu = UserGroupMenuActionScope::where('data_scope', $model->data_scope)->count();
        if($menu > 0) {
            return Code::INSIDE_ERROR_2;
        }

        return $model->delete();
    }

    /**
     * 编辑数据域
     * @param $id
     * @param $data
     * @return bool|int|null
     * todo：修改相对应使用域的地方
     */
    public function editScope($id, $data)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        if ($data['parent_id'] === 'flag') {
            $data['parent_id'] = $model->parent_id;
        }

        try {
            DB::beginTransaction();
            $childCount = $this->where('parent_id', $id)->count();
            if (!isset($data['parent_id'])) {
                //修改单个full_title
                $data['full_title'] = $this->_setFullTitle($model->full_title, $data['title'], false, true);

                //修改子集full_title
                if ($childCount > 0) {
                    $this->_setChildFullTitle($id, $data['full_title']);
                }
                $data['data_scope'] = $this->_setScope(true);

                //编辑用户修改用户数据域
                $users = User::where('scope_id', $id)->get(['id', 'data_scope'])->toArray();
                if (count($users) > 0) {
                    foreach ($users as $v) {
                        $user['data_scope'] = $data['data_scope'] . substr($v['data_scope'], strlen($model->data_scope));
                        User::where('id', $v['id'])->update($user);
                    }
                }

                if ($childCount > 0) {
                    $this->_setChildModify($id, $data['full_title'], $data['data_scope'], $model->data_scope);
                }

                $data['parent_id'] = null;
                $model->updateOrCreate(['id' => $id], $data);
            } else {

                //判断父级是否为自己
                if (intval($data['parent_id']) === intval($id)) {
                    return Code::INSIDE_ERROR;
                }
                //判断父级是否为原父级
                if (intval($data['parent_id']) === $model->parent_id) {
                    //判断title是否发生变化
                    if (isset($data['title']) && $data['title'] != $model->title) {
                        $data['full_title'] = $this->_setFullTitle($model->full_title, $data['title']);
                        $model->updateOrCreate(['id' => $id], $data);
                    } else {
                        $model->updateOrCreate(['id' => $id], $data);
                    }
                } else {
                    $parent = $this->find($data['parent_id']);

                    if (!$parent) {
                        return Code::INSIDE_ERROR_1;
                    }

                    $all = $this->all(['id', 'parent_id', 'title', 'code', 'description'])->toArray();
                    $child = array_column($this->_getAllChild($all, $id), 'id');

                    if (in_array($data['parent_id'], $child)) {
                        return Code::INSIDE_ERROR_2;
                    }

                    $data['full_title'] = $this->_setFullTitle($parent->full_title, $data['title'], true);
                    $data['data_scope'] = $this->_setScope(false, $data['parent_id'], $parent->data_scope);

                    if ($childCount > 0) {
                        $this->_setChildModify($id, $data['full_title'], $data['data_scope'], $model->data_scope);
                    }

                    //编辑用户修改用户数据域
                    $users = User::where('scope_id', $id)->get(['id', 'data_scope'])->toArray();
                    if (count($users) > 0) {
                        foreach ($users as $v) {
                            $user['data_scope'] = $data['data_scope'] . substr($v['data_scope'], strlen($model->data_scope));
                            User::where('id', $v['id'])->update($user);
                        }
                    }

                    //编辑菜单功能数据域表
                    $menuActionScope = UserGroupMenuActionScope::where('data_scope', $model->data_scope)->get(['data_scope'])->toArray();
                    if (count($menuActionScope) > 0) {
                        UserGroupMenuActionScope::where('data_scope', $model->data_scope)->update(['data_scope' => $data['data_scope']]);
                    }

                    $model->updateOrCreate(['id' => $id], $data);
                }
            }

            DB::commit();
            return Code::INSIDE_TRUE;
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->throwError($e);
        }
    }

    /**
     * 获取数据域全部数据
     * @return array
     */
    public function getScopeListAll()
    {
        $model = $this->all(['id', 'parent_id', 'title'])->toArray();

        return $this->_setTree($model);
    }

    /**
     * 获取数据域详情
     * @param $id
     * @return null
     */
    public function getScope($id)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        $data = $model->toArray();

        $all = $this->all(['id', 'parent_id', 'full_title', 'title', 'code', 'data_scope', 'description'])->toArray();

        $child = $this->_getAllChild($all, $id);

        $data['children'] = $this->_setTree($child);

        return $data;
    }

    /**
     * 获取数据域列表
     * @param $limit
     * @param $sorter
     * @param $search
     * @return mixed
     */
    public function getScopeList($sorter, $search)
    {
        if ($sorter[0] == 'created_at') {
            $sorter[0] = 'data_scope';
        }
        $model = $this->orderBy($sorter[0], $sorter[1]);
        $model->select(['id', 'parent_id', 'full_title', 'title', 'code', 'data_scope', 'description', 'created_at']);

        foreach ($search as $key => $value) {
            switch ($key) {
                case 'title':
                    $model->where($key, 'like', '%' . $value . '%');
                    break;
            }
        }

        $model->with(['users' => function ($scope) {
            $scope->select([DB::raw('count(id) as user_count'), 'scope_id'])->groupBy('users.scope_id');
        }]);
        $data = $model->get()->toArray();

        if (count($data) > 0) {
            foreach ($data as $k => &$v) {
                if (count($v['users']) > 0) {
                    $v['user_count'] = $v['users'][0]['user_count'];
                } else {
                    $v['user_count'] = 0;
                }
                unset($v['users']);
            }

            return $this->_setTree($data);
        }

        return $data;
    }

    public function getScopeUsers($id, $limit, $sorter)
    {
        $model = $this->find($id);

        if (!$model) {
            return null;
        }

        $perPage = $limit > 0 ? $limit : $this->limit;
        $user = User::orderBy($sorter[0], $sorter[1]);
        $user->select(['username', 'gender', 'phone', 'job', 'data_scope', 'is_blocked', 'scope_id', 'department_id'])
            ->with(['department:id,title', 'scope:id,full_title'])
            ->where('scope_id', $id);

        return $user->paginate($perPage)->toArray();

    }

    /**
     * 设置数据域code
     * @type   true 没有父级  |  false   存在父级
     * @return string
     */
    public function _setScope($type, $parentId = null, $scope = '')
    {
        if ($type === true) {
            $lastScope = $this->where('parent_id', null)->orderBy('data_scope', 'desc')->limit(1)->first(['data_scope']);
        } else {
            $lastScope = $this->where('parent_id', $parentId)->orderBy('data_scope', 'desc')->limit(1)->first(['data_scope']);
        }

        if (isset($lastScope->data_scope)) {
            $scope = $this->_incDataOrg($lastScope->data_scope);
        } else {
            $scope = $scope . '01';
        }

        return $scope;
    }

    /**
     * 编辑数据域
     * @param $dataOrg
     * @return string
     */
    private function _incDataOrg($dataOrg)
    {
        $pre = substr($dataOrg, 0, strlen($dataOrg) - 2);
        $seed = intval(substr($dataOrg, -2)) + 1;

        return $pre . str_pad($seed, 2, "0", STR_PAD_LEFT);
    }

    /**
     * 设置单个数据域全路径名称
     * @param $fullTitle full_title
     * @param $title title
     * @return string
     */
    public function _setFullTitle($fullTitle, $title, $type = false, $flag = false)
    {
        $newFullTitle = explode('\\', $fullTitle);
        if ($flag === false) {
            if ($type === true) {
                array_push($newFullTitle, $title);
            } else {
                array_pop($newFullTitle);
                array_push($newFullTitle, $title);
            }
            $res = implode('\\', $newFullTitle);
        } else {
            $res = $title;
        }

        return $res;
    }

    /**
     * 设置子集full_title
     * @param $id 父级id
     * @param $title 父级full_title
     */
    public function _setChildFullTitle($id, $title)
    {
        $model = $this->where('parent_id', $id)->get(['id', 'title'])->toArray();

        foreach ($model as $v) {

            $fullTitle['full_title'] = $title . '\\' . $v['title'];

            $this->where('id', $v['id'])->update($fullTitle);

            $child = $this->where('parent_id', $v['id'])->count();

            if ($child > 0) {
                $this->_setChildFullTitle($v['id'], $fullTitle['full_title']);
            }
        }
    }

    /**
     * 获取指定数据域下的子集
     * @param $data 数据集合
     * @param $id 父级id
     * @return array
     */
    public function _getAllChild($data, $id)
    {
        $arr = [];
        foreach ($data as $v) {
            if ($v['parent_id'] == $id) {
                $child['id'] = $v['id'];
                $child['title'] = $v['title'];
                $child['code'] = $v['code'];
                $child['description'] = $v['description'];
                $child['parent_id'] = $v['parent_id'];
                $arr[] = $child;
                $arr = array_merge($arr, $this->_getAllChild($data, $v['id']));
            }
        }
        return $arr;
    }

    /**
     * 设置子集full_title，scope
     * @param $id 父级id
     * @param $title    父级full_title
     * @param $scope    父级scope
     */
    public function _setChildModify($id, $title, $scope, $oldScope = '')
    {
        $model = $this->where('parent_id', $id)->get(['id', 'title', 'data_scope'])->toArray();

        foreach ($model as $v) {
            $data['full_title'] = $title . '\\' . $v['title'];
            $data['data_scope'] = $scope . substr($v['data_scope'], strlen($oldScope));
            $dataScope = $this->find($v['id'], ['data_scope']);
            $this->where('id', $v['id'])->update($data);

            $child = $this->where('parent_id', $v['id'])->count();
            //修改用户data_scope
            $users = User::where('scope_id', $v['id'])->get(['id', 'data_scope'])->toArray();
            if (count($users) > 0) {
                foreach ($users as $value) {
                    $user['data_scope'] = $data['data_scope'] . substr($value['data_scope'], strlen($dataScope->data_scope));
                    User::where('id', $value['id'])->update($user);
                }
            }

            if ($child > 0) {
                $this->_setChildModify($v['id'], $data['full_title'], $data['data_scope'], $v['data_scope']);
            }
        }
    }

    /**
     * 生成树状结构数据
     * @param $arr
     * @return array
     */
    public function _setTree($arr)
    {
        //构造数据
        $items = [];
        foreach ($arr as $v) {
            $items[$v['id']] = $v;
        }

        //遍历数据 生成树状结构
        $tree = [];
        foreach ($items as $key => $value) {
            if (isset($items[$value['parent_id']])) {
                $items[$value['parent_id']]['children'][] = &$items[$key];
            } else {
                $tree[] = &$items[$key];
            }
        }

        return $tree;
    }

}
